package com.polymer.app.encryption;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.springframework.util.Base64Utils;


public class AESEncryption {


    public static final String ALGORITHM_LONG_NAME = "AES/CBC/PKCS5Padding";

    public static final String ALGORITHM_SHORT_NAME = "AES";

    //定义向量为{0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}
    public static final byte iv0 = (byte) 0x12;

    public static final byte iv1 = (byte) 0x34;

    public static final byte iv2 = (byte) 0x56;

    public static final byte iv3 = (byte) 0x78;

    public static final byte iv4 = (byte) 0x90;

    public static final byte iv5 = (byte) 0xAB;

    public static final byte iv6 = (byte) 0xCD;

    public static final byte iv7 = (byte) 0xEF;

    public static final byte iv8 = (byte) 0x12;

    public static final byte iv9 = (byte) 0x34;

    public static final byte iv10 = (byte) 0x56;

    public static final byte iv11 = (byte) 0x78;

    public static final byte iv12 = (byte) 0x90;

    public static final byte iv13 = (byte) 0xAB;

    public static final byte iv14 = (byte) 0xCD;

    public static final byte iv15 = (byte) 0xEF;

    /**
     * 系统内加密方法，返回base64格式密文
     * @param plainString 原文字符串
     * @param keyString 密钥字符串，需经过转换后为真正的密钥
     * @return 成功：base64格式密文；失败：null
     */
    public static String sysEncode(String plainString, String keyString) {
        String retValue = null;

        if (plainString == null || plainString.equals("") || keyString == null || keyString.equals("")) {//原文或密钥任一为空，则返回失败
            return null;
        }

        byte[] btKey = strToKey(keyString);

        retValue = encode(plainString, btKey);

        return retValue;
    }

    /**
     * 加密，返回base64格式密文
     * @param plainString 原文字符串
     * @param keyString 密钥字符串
     * @return 成功：base64格式密文；失败：null
     */
    public static String encode(String plainString, String keyString) {
        String retValue = null;

        if (plainString == null || plainString.equals("") || keyString == null || keyString.equals("")) {//原文或密钥任一为空，则返回失败
            return null;
        }

        byte[] btKey = null;
        try {
            btKey = keyString.getBytes(Global.ENCODING);
        } catch (UnsupportedEncodingException e) {
            System.out.println("catch exception when getBytes：{0}"+ e.getMessage());
            //e.printStackTrace();
        }

        retValue = encode(plainString, btKey);

        return retValue;
    }

    /**
     * 加密，返回base64格式密文
     * @param plainString 原文字符串
     * @param btKey 密钥数据，byte数组
     * @return 成功：base64格式密文；失败：null
     */
    public static String encode(String plainString, byte[] btKey) {
        String retValue = null;

        if (plainString == null || plainString.equals("") || btKey == null) {//原文或密钥任一为空，则返回失败
            return null;
        }

        try {
            SecretKeySpec key = new SecretKeySpec(btKey, ALGORITHM_SHORT_NAME);
            Cipher cipher = Cipher.getInstance(ALGORITHM_LONG_NAME);// 创建密码器   
            //组织密钥向量
            byte[] iv = { iv0, iv1, iv2, iv3, iv4, iv5, iv6, iv7, iv8, iv9, iv10, iv11, iv12, iv13, iv14, iv15 };
            final IvParameterSpec ivparameter = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, key, ivparameter);// 初始化   
            byte[] byteContent = plainString.getBytes(Global.ENCODING);
            byte[] encodeByte = cipher.doFinal(byteContent);
            retValue = new String(Base64Utils.encode(encodeByte), Global.ENCODING);
        } catch (Exception e) {
            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //e.printStackTrace();
            //        } catch (NoSuchPaddingException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (InvalidKeyException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (UnsupportedEncodingException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (IllegalBlockSizeException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (BadPaddingException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (InvalidAlgorithmParameterException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //e.printStackTrace();
        }
        /*catch (NoSuchProviderException e) {
        	e.printStackTrace();
        }*/

        return retValue;
    }

    /**
     * 使用自定义向量加密，返回BCD格式密文
     * @param plainString 原文字符串
     * @param btKey 密钥数据，byte数组
     * @param iv 向量数据，byte数组
     * @return 成功：BCD格式密文；失败：null
     */
    public static String encode(String plainString, byte[] btKey, byte[] iv) {
        String retValue = null;

        if (plainString == null || plainString.equals("") || btKey == null) {//原文或密钥任一为空，则返回失败
            return null;
        }

        try {
            SecretKeySpec key = new SecretKeySpec(btKey, ALGORITHM_SHORT_NAME);
            Cipher cipher = Cipher.getInstance(ALGORITHM_LONG_NAME);// 创建密码器   
            //组织密钥向量
            //byte[] iv = {iv0, iv1, iv2, iv3, iv4, iv5, iv6, iv7, iv8, iv9, iv10,
            //iv11, iv12, iv13, iv14, iv15};
            final IvParameterSpec ivparameter = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, key, ivparameter);// 初始化   
            byte[] byteContent = plainString.getBytes(Global.ENCODING);
            byte[] encodeByte = cipher.doFinal(byteContent);
//            Base64Utils.encode(encodeByte)
            //org.apache.tomcat.util.codec.binary.Base64.decodeBase64(encodeByte)
            retValue = new String(Base64Utils.encode(encodeByte), Global.ENCODING);
        } catch (Exception e) {
            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //e.printStackTrace();
            //        } catch (NoSuchPaddingException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (InvalidKeyException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (UnsupportedEncodingException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (IllegalBlockSizeException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (BadPaddingException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (InvalidAlgorithmParameterException e) {
            //            System.out.println("catch exception when encode：{0}"+ e.getMessage());
            //e.printStackTrace();
        }
        /*catch (NoSuchProviderException e) {
        	e.printStackTrace();
        }*/

        return retValue;
    }

    /**
     * 系统内解密方法，将base64格式的密文字符串解密为原文字符串
     * @param encodedString base64格式的密文字符串
     * @param keyString 密钥字符串，需经过转换后为真正的密钥
     * @return 成功：原文字符串；失败：null
     */
    public static String sysDecode(String encodedString, String keyString) {
        String retValue = null;

        if (encodedString == null || encodedString.equals("") || keyString == null || keyString.equals("")) {//原文或密钥任一为空，则返回失败
            return null;
        }

        byte[] btKey = strToKey(keyString);//根据一定规则对密钥字符串转为byte形式的密钥数据

        retValue = decode(encodedString, btKey);

        return retValue;
    }
    
    public static void main(String[] args) {
        String a="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";
        System.out.println(a);
        String key="TC09192017062707";
        String decode = decode(a,key);
        System.out.println(decode);
        System.out.println(encode(decode,key));
    }

    /**
     * 解密，返回原文字符串
     * @param encodedString base64格式的密文字符串
     * @param keyString 密钥字符串
     * @return 成功：原文字符串；失败：null
     */
    public static String decode(String encodedString, String keyString) {
        String retValue = null;

        if (encodedString == null || encodedString.equals("") || keyString == null || keyString.equals("")) {//原文或密钥任一为空，则返回失败
            return null;
        }

        byte[] btKey = null;
        try {
            btKey = keyString.getBytes(Global.ENCODING);
        } catch (UnsupportedEncodingException e) {
            System.out.println("catch exception when getBytes()：{0}"+ e.getMessage());
            //e.printStackTrace();
        }

        retValue = decode(encodedString, btKey);

        return retValue;
    }

    /**
     * 解密，返回原文字符串
     * @param encodedString base64格式的密文字符串
     * @param btKey 密钥数据，byte数组
     * @return 成功：原文字符串；失败：null
     */
    public static String decode(String encodedString, byte[] btKey) {
        String retValue = null;

        if (encodedString == null || encodedString.equals("") || btKey == null) {//原文或密钥任一为空，则返回失败
            return null;
        }

        try {
            SecretKeySpec key = new SecretKeySpec(btKey, ALGORITHM_SHORT_NAME);
            Cipher cipher = Cipher.getInstance(ALGORITHM_LONG_NAME);// 创建密码器   
            //组织密钥向量
            byte[] iv = { iv0, iv1, iv2, iv3, iv4, iv5, iv6, iv7, iv8, iv9, iv10, iv11, iv12, iv13, iv14, iv15 };
            final IvParameterSpec ivparameter = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, key, ivparameter);// 初始化   
            byte[] byteContent = Base64Utils.decode(encodedString.getBytes(Global.ENCODING));
            byte[] decodeByte = cipher.doFinal(byteContent);
            retValue = new String(decodeByte, Global.ENCODING);
        } catch (Exception e) {
            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //e.printStackTrace();
            //        } catch (NoSuchPaddingException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (InvalidKeyException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (UnsupportedEncodingException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (IllegalBlockSizeException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (BadPaddingException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (InvalidAlgorithmParameterException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //e.printStackTrace();
        }
        /*catch (NoSuchProviderException e) {
        	e.printStackTrace();
        }*/

        return retValue;
    }

    /**
     * 用自定义的向量进行解密，返回原文字符串
     * @param encodedString base64格式的密文字符串
     * @param btKey 密钥数据，byte数组
     * @param iv 向量数据，byte数组
     * @return 成功：原文字符串；失败：null
     */
    public static String decode(String encodedString, byte[] btKey, byte[] iv) {
        String retValue = null;

        if (encodedString == null || encodedString.equals("") || btKey == null) {//原文或密钥任一为空，则返回失败
            return null;
        }

        try {
            SecretKeySpec key = new SecretKeySpec(btKey, ALGORITHM_SHORT_NAME);
            Cipher cipher = Cipher.getInstance(ALGORITHM_LONG_NAME);// 创建密码器   
            //组织密钥向量
            //byte[] iv = {iv0, iv1, iv2, iv3, iv4, iv5, iv6, iv7, iv8, iv9, iv10,
            //iv11, iv12, iv13, iv14, iv15};
            final IvParameterSpec ivparameter = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, key, ivparameter);// 初始化   
            byte[] byteContent = Base64Utils.decode(encodedString.getBytes(Global.ENCODING));
            byte[] decodeByte = cipher.doFinal(byteContent);
            retValue = new String(decodeByte, Global.ENCODING);
        } catch (Exception e) {
            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //e.printStackTrace();
            //        } catch (NoSuchPaddingException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (InvalidKeyException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (UnsupportedEncodingException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (IllegalBlockSizeException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (BadPaddingException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //            //e.printStackTrace();
            //        } catch (InvalidAlgorithmParameterException e) {
            //            System.out.println("catch exception when decode()：{0}"+ e.getMessage());
            //e.printStackTrace();
        }
        /*catch (NoSuchProviderException e) {
        	e.printStackTrace();
        }*/

        return retValue;
    }

    /**
     * 将输入的字符串按规则转成系统所用的加密KEY
     * 规则为计算字符串的md5值，然后执行取反操作，再将前9个字节顺序颠倒，最后再将后8个字节顺序颠倒
     * @param keyString 密钥字符串
     * @return 经过转换后的密钥数据，byte数组
     */
    private static byte[] strToKey(String keyString) {
        if (keyString == null) {
            return null;
        }
        byte[] retValue = null;

        byte[] btString = null;
        try {
            btString = keyString.getBytes(Global.ENCODING);
        } catch (UnsupportedEncodingException e) {
            System.out.println("catch exception when getBytes()：{0}"+ e.getMessage());
            //e.printStackTrace();
        }

        if (btString != null) {
            MessageDigest md = null;
            try {
                md = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                System.out.println("catch exception when MessageDigest.getInstance()：{0}"+ e.getMessage());
                //e.printStackTrace();
            }
            md.update(btString);

            //获取字符串MD5值
            retValue = md.digest();

            //执行取反操作
            for (int i = 0; i < retValue.length / 4; i++) {
                byte swap;
                //前一半字节每字节取反，然后位置反向
                swap = (byte) ~retValue[i];
                retValue[i] = (byte) ~retValue[retValue.length / 2 - i];
                retValue[retValue.length / 2 - i] = swap;
                //后一半字节每字节取反，然后位置反向
                swap = (byte) ~retValue[retValue.length / 2 + i];
                retValue[retValue.length / 2 + i] = (byte) ~retValue[retValue.length - i - 1];
                retValue[retValue.length - i - 1] = swap;
            }
        }

        return retValue;
    }

    /**
     * 将二进制转换成16进制
     * 
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        if (buf == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase(Locale.ENGLISH));
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     * 
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr == null) {
            return null;
        }
        if (hexStr.length() < 1) {
            return null;
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

}

class Global {
    public final static String ENCODING = "UTF-8";
    
    /*public static String sysPrivateKey = null;
    
    public final static String DATABASECONFIGERROR_CODEID = "91010002";
    public final static String SYSTEMERROR_CODEID = "91010001";
    public final static String SYSTEMERROR_CODE = "SYSTEM_ERROR";*/
}
